package com.mcp.server.utils;

import cn.hutool.core.net.url.UrlBuilder;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.mcp.server.enums.DirectionLiteType;
import lombok.Data;
import lombok.ToString;

import java.util.List;
import java.util.Map;
import java.util.Objects;

public class BaiduMapUtils {

    private final String AK;    // 百度地图ak

    private static final String SRC = "webapp.eselect.mcpserver";

    private static final String BASE_URL = "https://api.map.baidu.com";


    public BaiduMapUtils(String ak) {
        this.AK = ak;
    }


    /**
     * 获取指定区域的天气信息
     *
     * @param district_id 区域ID，用于标识要查询天气的具体地区
     * @return 天气信息的响应结果，以字符串形式返回
     */
    public String getWeather(String district_id) {
        String url = UrlBuilder.of(BASE_URL + "/weather/v1/")
                .addQuery("district_id", district_id)
                .addQuery("data_type", "all")
                .addQuery("ak", AK)
                .build();
        HttpResponse response = HttpRequest.get(url).execute();
        return parseRestfulResponse(response);
    }

    /**
     * 根据起终点坐标规划驾车出行路线和耗时,支持10个途经点 支持设置偏好：常规路线、不走高速、躲避拥堵
     *
     * @param originCityName      起点城市名称
     * @param destinationCityName 目标城市名称
     * @param waypoints           途经城市
     * @param tactics             路线偏好 0：常规路线(时间最短) 1：不走高速 2：躲避拥堵 3：最短距离 4：花费最少 5：大路优先 6：表示避开轮渡
     * @return 路线信息
     */
    public String getDirectionLiteByDriving(String originCityName, String destinationCityName,
                                            List<String> waypoints, Integer tactics) {
        CityCoordinates originCityCoordinates = getCityCoordinates(originCityName);
        CityCoordinates destinationCityCoordinates = getCityCoordinates(destinationCityName);
        String waypointsStr = "";
        if (waypoints != null && !waypoints.isEmpty()) {
            StringBuilder stringBuilder = new StringBuilder();
            for (String waypoint : waypoints) {
                CityCoordinates cityCoordinates = getCityCoordinates(waypoint);
                stringBuilder.append(cityCoordinates.getCoordinates()).append("|");
            }
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            waypointsStr = stringBuilder.toString();
        }
        String url = UrlBuilder.of(BASE_URL + "/directionlite/v1/driving")
                .addQuery("origin", originCityCoordinates.getCoordinates())
                .addQuery("destination", destinationCityCoordinates.getCoordinates())
                .addQuery("ak", AK)
                .addQuery("tactics", tactics)
                .addQuery("waypoints", waypointsStr)
                .build();
        HttpResponse response = HttpRequest.get(url).execute();
        return parseRestfulResponse(response);
    }

    /**
     * 骑行路线规划
     * 根据起终点坐标规划骑行出行路线和耗时，支持普通自行车和电动自行车出行方式
     *
     * @param originCityName      起点城市名称
     * @param destinationCityName 目标城市名称
     * @param ridingType          默认0 0：普通自行车 1：电动自行车
     * @return 路线信息
     */
    public String getDirectionLiteByRiding(String originCityName, String destinationCityName, String ridingType) {
        CityCoordinates originCityCoordinates = getCityCoordinates(originCityName);
        CityCoordinates destinationCityCoordinates = getCityCoordinates(destinationCityName);
        String url = UrlBuilder.of(BASE_URL + "/directionlite/v1/riding")
                .addQuery("origin", originCityCoordinates.getCoordinates())
                .addQuery("destination", destinationCityCoordinates.getCoordinates())
                .addQuery("ak", AK)
                .addQuery("riding_type", ridingType)
                .build();
        HttpResponse response = HttpRequest.get(url).execute();
        return parseRestfulResponse(response);
    }

    /**
     * 步行路线规划
     * 根据起终点坐标规划步行出行路线和耗时
     *
     * @param originCityName      起点城市名称
     * @param destinationCityName 目标城市名称
     * @return 路线信息
     */
    public String getDirectionLiteByWalking(String originCityName, String destinationCityName) {
        CityCoordinates originCityCoordinates = getCityCoordinates(originCityName);
        CityCoordinates destinationCityCoordinates = getCityCoordinates(destinationCityName);
        String url = UrlBuilder.of(BASE_URL + "/directionlite/v1/walking")
                .addQuery("origin", originCityCoordinates.getCoordinates())
                .addQuery("destination", destinationCityCoordinates.getCoordinates())
                .addQuery("ak", AK)
                .build();
        HttpResponse response = HttpRequest.get(url).execute();
        return parseRestfulResponse(response);
    }

    /**
     * 公交路线规划
     * 根据起终点坐标规划同城公共交通出行路线和耗时，支持公交、地铁出行方式
     *
     * @param originCityName      起点城市名称
     * @param destinationCityName 目标城市名称
     * @return 路线信息
     */
    public String getDirectionLiteByTransit(String originCityName, String destinationCityName) {
        CityCoordinates originCityCoordinates = getCityCoordinates(originCityName);
        CityCoordinates destinationCityCoordinates = getCityCoordinates(destinationCityName);
        String url = UrlBuilder.of(BASE_URL + "/directionlite/v1/transit")
                .addQuery("origin", originCityCoordinates.getCoordinates())
                .addQuery("destination", destinationCityCoordinates.getCoordinates())
                .addQuery("ak", AK)
                .build();
        HttpResponse response = HttpRequest.get(url).execute();
        return parseRestfulResponse(response);
    }

    /**
     * 生成调起百度PC或Web地图的URL地址   只支持公交、驾车、步行路线规划
     *
     * @param originCityName      起点城市名称
     * @param destinationCityName 目标城市名称
     * @param directionLiteType   只支持 transit、driving、walking，分别表示公交、驾车和步行
     * @return 调起百度PC或Web地图的URL地址
     */
    public String generateDirectionLiteMap(String originCityName, String destinationCityName, DirectionLiteType directionLiteType) {
        if (directionLiteType == null || !"transit,driving,walking".contains(directionLiteType.getType())){
            throw new IllegalArgumentException("mode参数错误 只支持公交: transit、驾车: driving、步行: walking");
        }
        CityCoordinates originCityCoordinates = getCityCoordinates(originCityName);
        String originExtractCityName = extractCityName(originCityName);
        CityCoordinates destinationCityCoordinates = getCityCoordinates(destinationCityName);
        String destinationExtractCityName = extractCityName(destinationCityName);
        return UrlBuilder.of("http://api.map.baidu.com/direction")
                .addQuery("origin", "latlng:"+ originCityCoordinates.getCoordinates() +"|name:" + originCityName)
                .addQuery("destination", "latlng:"+ destinationCityCoordinates.getCoordinates() +"|name:" + destinationCityName)
                .addQuery("mode", directionLiteType.getType())
                .addQuery("output", "html")
                .addQuery("coord_type", "bd09ll")
                .addQuery("origin_region",originExtractCityName)
                .addQuery("destination_region",destinationExtractCityName)
                .addQuery("src", SRC)
                .build();
    }


    /**
     * 根据城市名称获取地理坐标
     *
     * @param cityName 城市名称
     * @return 地理坐标
     */
    public CityCoordinates getCityCoordinates(String cityName) {
        String url = UrlBuilder.of(BASE_URL + "/geocoding/v3/")
                .addQuery("address", cityName)
                .addQuery("output", "json")
                .addQuery("ak", AK)
                .build();
        HttpResponse response = HttpRequest.get(url).execute();
        String parsed = parseRestfulResponse(response);
        if (parsed == null) {
            return null;
        }
        JSONObject location = (JSONObject) JSONUtil.toBean(parsed, Map.class).get("location");
        return JSONUtil.toBean(location, CityCoordinates.class);
    }

    public String parseRestfulResponse(HttpResponse response) {
        String body = response.body();
        if (StrUtil.isEmptyIfStr(body)) {
            return null;
        }
        Object result = JSONUtil.toBean(body, Map.class).get("result");
        if (Objects.isNull(result)) {
            return null;
        }
        return result.toString();
    }

    /**
     * 从完整地址中提取市级别及以上的城市名称
     * 例如：江西省南昌市南昌县xxx -> 江西省南昌市
     *
     *
     * @param fullAddress 完整的地址信息
     * @return 市级别及以上的城市名称
     */
    public String extractCityName(String fullAddress) {
        if (StrUtil.isEmpty(fullAddress)) {
            return null;
        }
        // 常见的市级行政单位后缀
        String[] citySuffixes = {"市", "自治州", "地区", "盟"};

        for (String suffix : citySuffixes) {
            int index = fullAddress.indexOf(suffix);
            if (index > 0) {
                // 如果包含省级信息，则返回完整的省+市名称
                return fullAddress.substring(0, index + suffix.length());
            }
        }
        // 如果没有找到市级别单位，则返回空
        return null;
    }


    /**
     * 城市坐标 实体类
     */
    @Data
    @ToString
    class CityCoordinates {
        private double lat; // 纬度
        private double lng; // 经度

        public String getCoordinates() {
            return lat + "," + lng;
        }
    }
}
